package com.bank.GuiZhou;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.os.Message;
import android.telecom.Call;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;

import com.jq.printer.JQPrinter;
import com.jq.printer.esc.ESC;
import com.jq.printer.Printer_define;
import com.siecom.framework.appinterface.APDU_RESP;
import com.siecom.framework.appinterface.Api;
import com.siecom.framework.bean.IdentityInfoBean;
import com.siecom.framework.constconfig.Config;
import com.siecom.framework.device.SiecomDevice;
import com.siecom.framework.module.BankCardModule;
import com.siecom.framework.module.IdentityModule;
import com.siecom.framework.module.KeyBroadModule;
import com.siecom.framework.module.KeyBroadOption;
import com.siecom.tools.ByteTool;
import com.siecom.tools.FileUnits;
import com.siecom.tools.FingerUnit;
import com.siecom.tools.LogUtil;
import com.siecom.tools.SingletonThreadPool;
import com.siecom.tools.StringUtil;
import com.siecom.tools.Timer;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.Set;
import java.util.TimerTask;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

import static com.siecom.framework.module.BankCardModule.decodecardNo;
import static com.siecom.framework.module.BankCardModule.getCardNo;

public class ZGBluedeviceManager implements ZGBluedeviceInterface {

    private static final String TAG = ZGBluedeviceManager.class.getSimpleName();
    private Api api = Api.getApi();

    private static ZGBluedeviceManager manager = new ZGBluedeviceManager();
    public static ZGBluedeviceManager getInstance(){
        return manager;
    }

    @Override
    public Integer readerIdConnect() {
        int ret = api.IDCard_Open();
        if (ret == 0){
            IsConId = true;
            return 0;
        }
        else{
            IsConId = false;
            return 1;
        }
    }

    @Override
    public Integer readerIdDisconnect() {
        int ret = api.IDCard_Close();
        if(ret == 0){
            IsConId = false;
            return 0;
        }else {
            return 1;
        }
    }


    public int cardType = 0;  //卡类型 1--IC  2--非接NFC
    /**
     * 打开银行卡
     * @return
     */
    @Override
    public Integer readerCardConnect() {
        int timeOutMs = 20*1000;
        Timer timer = new Timer(timeOutMs);
        timer.start();
        cardType = 0;

        int ret = -1;
        ret = api.Picc_Close();
        ret = api.Picc_Open();
        Log.e(TAG,"Picc_Open ret==" + ret);
        while (true){
            if (timer.timeOut()){
                Log.e(TAG,"timer.timeOut");
                api.Picc_Close();
                api.Icc_Close((byte) 0x00);
                return ConstDefine.TIMEOUT;
            }
            ret = api.Icc_Detect((byte) 0x00);
            if(ret == 0){
                byte[] ATR = new byte[100];
                for(int i = 0;i < 3; i++){
                    ret = api.Icc_Open((byte) 0x00, (byte) 0x01, ATR); // IC卡上电
                    if (ret == 0){
                        cardType = 1;
                        api.Picc_Close(); //检测到插卡后 关闭非接
                        Log.e(TAG,"cardType == " + cardType);
                        break;
                    }
                    api.Icc_Close((byte) 0x00);
                }
                if(ret == 0){
                    return 0;
                }else {
                    return 1;
                }

            }else {
                api.Icc_Close((byte) 0x00);
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            byte CardType[] = new byte[3];
            byte SerialNo[] = new byte[50];
            ret = api.Picc_Check((byte) 0x01, CardType, SerialNo);
            if(ret == 0){
                for (int i = 0; i < 3; i++) {
                    ret = api.Picc_Reset();
                    if(ret == 0){
                        cardType = 2;
                        Log.e(TAG,"cardType == " + cardType);
                        api.Icc_Close((byte) 0x00); //检测到非接后关闭IC
                        break;
                    }
                }
                if (ret == 0){
                    IsConIC = true;
                    return 0;
                }else {
                    return 1;
                }

            }else {
                IsConIC = false;
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public Integer readerCardDisconnect() {
        api.Icc_Close((byte) 0x00);
        api.Picc_Close();
        IsConIC = false;
        return 0;
    }
    private JQPrinter printer = new JQPrinter(Printer_define.PRINTER_MODEL.JLP351);
    public String ptBlueName = "VMP02-00000000";
    @Override
    public Integer printerConnect() {
        Set<BluetoothDevice> devices = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
        String address = "";
        for (BluetoothDevice device : devices){
            if(device.getName().equals(ptBlueName)){
                address = device.getAddress();
                break;
            }
        }

        boolean isOpen = printer.open(address);
        if(isOpen)
            return 0;
        else
            return 1;
    }

    @Override
    public Integer printerDisConnect() {
        boolean b = printer.close();
        if (b){
            return 0;
        } else
        return 1;
    }

    @Override
    public Integer pwdConnect() {
        int ret = -1;
        try {
            for (int i = 0; i < 3; i++) {
                ret = api.Handshake();
                if (ret == 0) {
                    break;
                }
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();

        }
        if (ret == 0){
            return ret;
        }else {
            return 1;
        }

    }

    @Override
    public Integer pwdDisconnect() {
        api.GetPin_quit();
        return 0;
    }

    @Override
    public Integer blueFingerConnect() {
        for (int i = 0; i < 3; i++) {
            int iret = api.TCD_Open();
            if (iret == 0){
                BlueFinIsConFin = true;
                return 0;
            }
            api.TCD_Close();
        }
        BlueFinIsConFin = false;
        return 1;
    }

    @Override
    public Integer blueFingerDisconnect() {
        int ret = api.TCD_Close();
        if (ret == 0){
            BlueFinIsConFin = false;
            return ret;
        }else {
            return 1;
        }
    }

    @Override
    public String getFFInfo() {
        String retStr = "";
        final JSONObject jb = new JSONObject();
        final Timer timer = new Timer(20*1000);
        timer.start();
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                int type = -1;
                if (cardType == 1){ //IC 卡
                    type = 0;
                }else if(cardType == 2){
                    type = 1;
                }else return "";

                while (true){
                    if(timer.timeOut()){
                        jb.put(ConstDefine.requestCode,ConstDefine.TIMEOUT);
                        jb.put(ConstDefine.requestResult,"timeout,please try again!");
                        readerCardDisconnect();
                        break;
                    }

                    String str = BankCardModule.getInstance().transBeforeOnline((byte) type);
                    if(TextUtils.isEmpty(str)){
                        jb.put(ConstDefine.requestCode,ConstDefine.ERROR);
                        jb.put(ConstDefine.requestResult,"read card error,please try again!");
                        readerCardDisconnect();
                        break;
                    }

                    jb.put(ConstDefine.get55Data,str); // 55域

                    jb.put(ConstDefine.requestCode,ConstDefine.SUCCESS);
                    jb.put(ConstDefine.requestResult,"success");
                    break;
                }

                return jb.toString();
            }
        };
        FutureTask<String> futureTask = new FutureTask<>(callable);
        new Thread(futureTask).start();
        try {
            retStr = futureTask.get();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return retStr;
    }

    @Override
    public String writeIcCard(String msg) {
        final JSONObject jb = new JSONObject();
        final String arpc = "910A222A0C26DE7B9AEF3030";//91开头，脚本是72开头
//                                    final String script = "72199F1804D7C4E3C1861004DA9F790A0000000001005A90B2E100";
        final String script = msg;

        /**
         * 这里可以做ARPC校验，这里是数据是测试的数据，百分百失败的
         */

            // TODO Auto-generated method stub
            byte[] ScriptResult = new byte[1024];
            byte[] TC = new byte[1024];
            if(cardType == 1){
                cardType = 0; //插卡类型
            }else if(cardType == 2){
                cardType = 1; //非接类型
            }
            try {
                /**
                 * 这是同步接口
                 */
                int ret = SiecomDevice.SyncARPCExecuteScript(cardType, arpc, script, ScriptResult, TC);
//                                            int ret = SiecomDevice.SyncValidateARPC(ByteTool.hexStr2Bytes(arpc));
                Log.e("ARPC", "ret:" + ret + ",ScriptResult==" + ByteTool.bytearrayToHexString(ScriptResult, 1024));
                if (ret == 0){
                    jb.put(ConstDefine.requestCode,ConstDefine.SUCCESS);
                    jb.put(ConstDefine.requestResult,"success");
                }else {
                    jb.put(ConstDefine.requestCode,ConstDefine.ERROR);
                    jb.put(ConstDefine.requestResult,"data error ,please check you data!");
                }

                return jb.toString();
            } catch (JSONException e) {
                e.printStackTrace();
            }


        return jb.toString();

    }

    @Override
    public String readIcCard() {
        String retStr = "";
        final JSONObject jb = new JSONObject();
        final Timer timer = new Timer(20*1000);
        timer.start();
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                int type = -1;
                if (cardType == 1){ //IC 卡
                   type = 0;
                }else if(cardType == 2){
                    type = 1;
                }else return "";

                while (true){
                    if(timer.timeOut()){
                        jb.put(ConstDefine.requestCode,ConstDefine.TIMEOUT);
                        jb.put(ConstDefine.requestResult,"timeout,please try again!");
                        readerCardDisconnect();
                        break;
                    }

                    String str = BankCardModule.getInstance().transBeforeOnline((byte) type);
                    if(TextUtils.isEmpty(str)){
                        jb.put(ConstDefine.requestCode,ConstDefine.ERROR);
                        jb.put(ConstDefine.requestResult,"read card error,please try again!");
                        readerCardDisconnect();
                        break;
                    }
                    String cardNo = "";
                    LogUtil.e(TAG,"transBeforeOnline str == " + str);
                    if (str.indexOf("5A") != -1) {
                        cardNo = StringUtil.tagParse("5A", str);
                        Log.e("cardno", cardNo);
                        int len5A = StringUtil.getTagLen(0, "5A", str);
                        if (len5A == 0) {
                            String tag57 = StringUtil.tagParse(len5A * 2 + 2, "57", str);
                            cardNo = getCardNo(tag57);
                            jb.put(ConstDefine.twodata,tag57); //  二磁道数据
                        }

                        if (cardNo == null || cardNo.length() == 0) {
                            continue;
                        }
                        if (cardNo.indexOf("F") != -1) {
                            cardNo = cardNo.substring(0, cardNo.indexOf("F"));
                        }

                    }


                    String tag5f20 = StringUtil.tagParse("5F20",str); // B 42姓名
                    LogUtil.e(TAG,"tag5f20=" + tag5f20);
                    String tag9F61 = StringUtil.tagParse("9F61",str);//D 44 证件号码
                    LogUtil.e(TAG,"tag9F61=" + tag9F61);
//                    String tag9F62 = StringUtil.tagParse("9F62",str); // C 43 证件类型
//                    LogUtil.e(TAG,"tag9F62=" + tag9F62);
                    String tag9F1F = StringUtil.tagParse("9F1F",str); // F 一磁道信息
                    LogUtil.e(TAG,"tag9F1F=" + tag9F1F);
                    String track2Str = StringUtil.tagParse("57",str); //E 二磁道信息
                    LogUtil.e(TAG,"track2==" + track2Str);

                    String tag5F24 = StringUtil.tagParse("5F24",str);//I 失效日期
                    LogUtil.e(TAG,"tag5F24=" + tag5F24);
                    String tag5F34 = StringUtil.tagParse("5F34",str);//J 序列号
                    LogUtil.e(TAG,"tag5F34=" + tag5F34);

                    jb.put(ConstDefine.twodata,track2Str);
                    jb.put(ConstDefine.pansequenceno,tag5F34); //序列号
                    jb.put(ConstDefine.date,tag5F24); //失效日期
                    jb.put(ConstDefine.name,tag5f20); //姓名
                    jb.put(ConstDefine.number,new String(ByteTool.hexStr2Bytes(tag9F61)).trim()); //证件号码
                    jb.put(ConstDefine.cardcode,cardNo); //卡号
                    jb.put(ConstDefine.tlvdata,str); // 55域

                    jb.put(ConstDefine.requestCode,ConstDefine.SUCCESS);
                    jb.put(ConstDefine.requestResult,"success");
                    break;
                }

                return jb.toString();
            }
        };
        FutureTask<String> futureTask = new FutureTask<>(callable);
        new Thread(futureTask).start();
        try {
            retStr = futureTask.get();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return retStr;
    }

    @Override
    public String readMagCard() {
        String retStr = "";
        final Timer timer = new Timer(20*1000);
        timer.start();
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                JSONObject jb = new JSONObject();
                int iret = -1;
                for (int i = 0; i < 3; i++) {
                    iret = api.Mcr_Open(); // 打开磁卡
                    Log.e(TAG, "MSR_CARD ret = " + iret);
                    if (iret == 0) {
                        break;
                    }
                    api.Mcr_Close();
                }

                while (true){
                    if(timer.timeOut()){
                        jb.put("requestCode",2);
                        jb.put("requestResult","timeout,please try again!");
                        api.Mcr_Close();
                        break;
                    }

                    int ret = api.Mcr_Check();
                    if (0 == ret) {
                        byte[] track1 = new byte[250];
                        byte[] track2 = new byte[250];
                        byte[] track3 = new byte[250];
                        Log.e(TAG, "Mcr_Check");
                        try {
                            ret = api.Mcr_Read((byte) 0, (byte) 0, track1, track2, track3);
                        } catch (ArrayIndexOutOfBoundsException e) {
                            e.printStackTrace();
                            continue;
                        }
                        Log.e(TAG, "ret = " + ret);
                        String cardNo = "";
                        if (ret > 0 && ret <= 7) {

                            String string = "";
                            if ((ret & 0x01) == 0x01)
                                string = "track1:" + new String(track1);
                            String oneMagneticTrack = new String(track1).trim();
                            jb.put(ConstDefine.onedata,oneMagneticTrack);
                            String twoMagneticTrack = "";
                            if ((ret & 0x02) == 0x02) {
                                string = string + "\n\ntrack2:" + new String(track2);
                                twoMagneticTrack = new String(track2).trim();
                                cardNo = decodecardNo(new String(track2).trim());
                                jb.put(ConstDefine.twodata,twoMagneticTrack);
                                jb.put(ConstDefine.cardcode,cardNo);

                            }
                            jb.put("requestCode",0);
                            jb.put("requestResult","success");
                            if ((ret & 0x04) == 0x04)
                                string = string + "\n\ntrack3:" + new String(track3);
                            String threeMagneticTrack = new String(track3).trim();
                            jb.put(ConstDefine.threedata,threeMagneticTrack);
                            Log.i("MSR", string );

                            Log.i(TAG, "Lib_MsrRead succeed!");
                            if (cardNo == null || cardNo.trim().length() == 0)
                                continue;
                            api.Mcr_Close();

                        } else {
                            continue;
                        }
                        break;
                    }
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }

                return jb.toString();
            }
        };
        FutureTask<String> task = new FutureTask<>(callable);
        new Thread(task).start();
        try {
            retStr = task.get();
            LogUtil.e(TAG,"readMagCard = " + retStr);
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return retStr;
    }

    private IdentityInfoBean bean;
    private byte[] recvBuf = new byte[1024];
    //读身份证
    @Override
    public String readIdCard() {
        long timeOutMs = 20*1000;
        String retStr = "";
        final Timer timer = new Timer(timeOutMs);
        timer.start();
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                JSONObject jb = new JSONObject();
                bean = new IdentityInfoBean();
                int i = 0;
                int ret = -1;
                while (true) {
                    if (timer.timeOut()){
                        jb.put("requestCode",2);
                        jb.put("requestResult","timeout");
                        api.IDCard_Close();
                        break;
                    }
                    synchronized (this) {
                        APDU_RESP ApduResp = new APDU_RESP();

                        try {
                            ret = api.IDCard_Test(ApduResp);
                        } catch (ArrayIndexOutOfBoundsException e) {
                            Log.e(TAG, e.getMessage());
                            //失败跳过再读取
                            continue;
                        }
                        Log.e(TAG, ret + "!!");
                        if (ret == 0) {
                            jb.put("requestCode",0);
                            jb.put("requestResult","success");
                            String tmpstr = "";
                            int myloopi, unicode;
                            String cardType = new String(ApduResp.DataOut, 248, 2, "UTF-16LE").trim();//证件类型

                            Log.e("cardType",cardType);

                            if(cardType.equals("I")){

                                String enName = new String(ApduResp.DataOut, 0, 120, "UTF-16LE").trim();

                                Log.e("enName",enName);

                                String fprSex = new String(ApduResp.DataOut, 120, 2, "UTF-16LE").trim();

                                String frpIDNo = new String(ApduResp.DataOut, 122, 30, "UTF-16LE").trim();

                                Log.e("frpIDNo",frpIDNo);

                                String countryCode = new String(ApduResp.DataOut, 152, 6, "UTF-16LE").trim();

                                Log.e("countryCode",countryCode);

                                String CHNName = new String(ApduResp.DataOut, 158, 30, "UTF-16LE").trim();

                                Log.e("CHNName",CHNName);

                                String validStart = new String(ApduResp.DataOut, 188, 16, "UTF-16LE").trim();

                                Log.e("validStart",validStart);

                                String validEnd = new String(ApduResp.DataOut, 204, 16, "UTF-16LE").trim();

                                Log.e("validEnd",validEnd);

                                String Birthday = new String(ApduResp.DataOut, 220, 16, "UTF-16LE").trim();

                                Log.e("Birthday",Birthday);

                                String idVer = new String(ApduResp.DataOut, 236, 4, "UTF-16LE").trim();

                                Log.e("idVer",idVer);

                                String issuingAuthorityCode = new String(ApduResp.DataOut, 240, 8, "UTF-16LE").trim();

                                Log.e("issuingAuthorityCode",issuingAuthorityCode);

                                System.arraycopy(ApduResp.DataOut, 256, recvBuf, 0, 1024);

                                bean.fullName = CHNName;
                                bean.icon = IdentityModule.getInstance().decodePhoto(recvBuf);
                                bean.birthday = Birthday;
                                bean.idNo = frpIDNo;
                                bean.idOrg = issuingAuthorityCode;
                                bean.beginDate = validStart;
                                bean.endDate = validEnd;
                                //  bean.idAddr = m_strAddress;
                                bean.countryCode= countryCode;
                                bean.nation = IdentityModule.countryMap.get(countryCode);
                                bean.sex = IdentityModule.findSexZW(Integer.parseInt(fprSex));
                                bean.cardType = "I";
                                bean.cardVer =idVer;
                                bean.enName =enName;

                            }else if(cardType.equals("J")){
                                String GAT_Name = (new String(ApduResp.DataOut, 0, 30, "UTF-16LE")).trim();
                                Log.e("GJ","GAT_NAME="+GAT_Name);
                                String GAT_SexCode = (new String(ApduResp.DataOut, 30, 2, "UTF-16LE")).trim();
                                Log.e("GJ","GAT_SexCode="+GAT_SexCode);
                                String ReserveA = (new String(ApduResp.DataOut, 32, 4, "UTF-16LE")).trim();
                                Log.e("GJ","ReserveA="+ReserveA);
                                String GAT_Birthday = (new String(ApduResp.DataOut, 36, 16, "UTF-16LE")).trim();
                                Log.e("GJ","GAT_Birthday="+GAT_Birthday);
                                String GAT_Address = (new String(ApduResp.DataOut, 52, 70, "UTF-16LE")).trim();
                                Log.e("GJ","GAT_Address="+GAT_Address);
                                String GAT_IDNo = (new String(ApduResp.DataOut, 122, 36, "UTF-16LE")).trim();
                                Log.e("GJ","GAT_IDNo="+GAT_IDNo);
                                String GAT_IssuingAuthority = (new String(ApduResp.DataOut, 158, 30, "UTF-16LE")).trim();
                                Log.e("GJ","GAT_IssuingAuthority="+GAT_IssuingAuthority);
                                String GAT_ValidStartDate = (new String(ApduResp.DataOut, 188, 16, "UTF-16LE")).trim();
                                Log.e("GJ","GAT_ValidStartDate="+GAT_ValidStartDate);
                                String GAT_ValidEndDate = (new String(ApduResp.DataOut, 204, 16, "UTF-16LE")).trim();
                                Log.e("GJ","GAT_ValidEndDate="+GAT_ValidEndDate);
                                String GAT_PassportNo = (new String(ApduResp.DataOut, 220, 18, "UTF-16LE")).trim();
                                Log.e("GJ","GAT_PassportNo="+GAT_PassportNo);
                                String GAT_IssuingNo = (new String(ApduResp.DataOut, 238, 4, "UTF-16LE")).trim();
                                Log.e("GJ","GAT_IssuingNo="+GAT_IssuingNo);
                                String ReserveB = (new String(ApduResp.DataOut, 242, 6, "UTF-16LE")).trim();
                                Log.e("GJ","ReserveB="+ReserveB);
                                String ReserveC = (new String(ApduResp.DataOut, 250, 6, "UTF-16LE")).trim();
                                Log.e("GJ","ReserveC="+ReserveC);
                                System.arraycopy(ApduResp.DataOut, 256, recvBuf, 0, 1024);


                                String Gender;
                                String GAT_Sex;
                                if(GAT_SexCode.equals("1")) {
                                    Gender = "男";
                                    GAT_Sex = "男";
                                } else {
                                    Gender = "女";
                                    GAT_Sex = "女";
                                }

                                bean.fullName = GAT_Name;
                                bean.icon = IdentityModule.getInstance().decodePhoto(recvBuf);
                                bean.birthday = GAT_Birthday;
                                bean.idNo = GAT_IDNo;
                                bean.idOrg = GAT_IssuingAuthority;
                                bean.beginDate = GAT_ValidStartDate;
                                bean.endDate = GAT_ValidEndDate;
                                bean.idAddr = GAT_Address;
//                                bean.countryCode= countryCode;
//                                bean.nation = countryMap.get(countryCode);
                                bean.sex = Gender;
                                bean.cardType = "J";
                                bean.reserveA = ReserveA;
                                bean.reserveB = ReserveB;
                                bean.reserveC = ReserveC;
                                bean.issuingNo= GAT_IssuingNo;
                                bean.passportNo= GAT_PassportNo;


                            }else { //二代身份证


                                for (myloopi = 0; myloopi < 15; myloopi++) {
                                    unicode = ((ApduResp.DataOut[myloopi * 2 + 1] & 0xff) << 8)
                                            | (ApduResp.DataOut[myloopi * 2 + 0] & 0xff);
                                    tmpstr += String.valueOf((char) unicode);
                                }
//                                m_strName = tmpstr;
                                jb.put("name",tmpstr);
                                // 性别
                                tmpstr = "";
                                for (myloopi = 0; myloopi < 1; myloopi++) {
                                    unicode = ((ApduResp.DataOut[30 + myloopi * 2 + 1] & 0xff) << 8)
                                            | (ApduResp.DataOut[30 + myloopi * 2 + 0] & 0xff);
                                    tmpstr += String.valueOf((char) unicode);
                                }
                                try {
                                    int sex_num = Integer.parseInt(tmpstr);
                                    tmpstr = IdentityModule.getInstance().findSexZW(sex_num);
                                } catch (NumberFormatException e) {
                                    //失败跳过再读取
                                    continue;
                                }
//                                m_strGender = tmpstr;
                                jb.put("sex",tmpstr);
                                // 民族
                                tmpstr = "";
                                for (myloopi = 0; myloopi < 2; myloopi++) {
                                    unicode = ((ApduResp.DataOut[32 + myloopi * 2 + 1] & 0xff) << 8)
                                            | (ApduResp.DataOut[32 + myloopi * 2 + 0] & 0xff);
                                    tmpstr += String.valueOf((char) unicode);
                                }
                                try {
                                    int nation_num = Integer.parseInt(tmpstr);
                                    tmpstr = IdentityModule.getInstance().findMinzuZW(nation_num);
                                } catch (NumberFormatException e) {
                                    //失败跳过再读取
                                    continue;
                                }
//                                m_strNation = tmpstr;
                                jb.put("nation",tmpstr);
                                // 出身日期
                                tmpstr = "";
                                for (myloopi = 0; myloopi < 8; myloopi++) {

                                    unicode = ((ApduResp.DataOut[36 + myloopi * 2 + 1] & 0xff) << 8)
                                            | (ApduResp.DataOut[36 + myloopi * 2 + 0] & 0xff);
                                    tmpstr += String.valueOf((char) unicode);

                                }
                                String m_strBornDate = tmpstr.substring(0, 4)
                                        + tmpstr.substring(4, 6)
                                        + tmpstr.substring(6, 8);
                                jb.put("birthday",m_strBornDate);

                                // 详址
                                tmpstr = "";
                                for (myloopi = 0; myloopi < 35; myloopi++) {
                                    unicode = ((ApduResp.DataOut[52 + myloopi * 2 + 1] & 0xff) << 8)
                                            | (ApduResp.DataOut[52 + myloopi * 2 + 0] & 0xff);
                                    tmpstr += String.valueOf((char) unicode);
                                }
                                Log.e("GJ","数据等于"+ tmpstr);
//                                m_strAddress = tmpstr;
                                jb.put("address",tmpstr);
                                // 身份证号码
                                tmpstr = "";
                                for (myloopi = 0; myloopi < 18; myloopi++) {
                                    unicode = ((ApduResp.DataOut[122 + myloopi * 2 + 1] & 0xff) << 8)
                                            | (ApduResp.DataOut[122 + myloopi * 2 + 0] & 0xff);
                                    tmpstr += String.valueOf((char) unicode);
                                }

//                                m_strNumber = tmpstr;
                                jb.put("idnumber",tmpstr);
                                // 签发机关
                                tmpstr = "";
                                for (myloopi = 0; myloopi < 15; myloopi++) {
                                    unicode = ((ApduResp.DataOut[158 + myloopi * 2 + 1] & 0xff) << 8)
                                            | (ApduResp.DataOut[158 + myloopi * 2 + 0] & 0xff);
                                    tmpstr += String.valueOf((char) unicode);
                                }
//                                m_strAuthor = tmpstr;
                                jb.put("issuer",tmpstr);
                                // 有限期限
                                tmpstr = "";
                                for (myloopi = 0; myloopi < 16; myloopi++) {
                                    unicode = ((ApduResp.DataOut[188 + myloopi * 2 + 1] & 0xff) << 8)
                                            | (ApduResp.DataOut[188 + myloopi * 2 + 0] & 0xff);
                                    tmpstr += String.valueOf((char) unicode);
                                }
                                String m_strPeriodFrom = tmpstr.substring(0, 8);
                                String m_strPeriodTo = "";
                                try {
                                    m_strPeriodTo = tmpstr.substring(8, 16);
                                } catch (ArrayIndexOutOfBoundsException e) {
                                    m_strPeriodTo = tmpstr.substring(8, 10);
                                }
                                jb.put("validDate",m_strPeriodFrom + "-" + m_strPeriodTo);
                                System.arraycopy(ApduResp.DataOut, 256, recvBuf, 0, 1024);
                                Bitmap headImage = IdentityModule.getInstance().decodePhoto(recvBuf);
                                jb.put(ConstDefine.picsrc,FileUnits.bitmapToBase64(headImage));
//                                String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/wltlib/";
//                                LogUtil.e(TAG,"照片路径:" + path);
//                                FileUnits.saveMyBitmap(headImage,"zp.bmp",path);
                            }

                            api.IDCard_Close();

                            break;
                        }else {
                            //ret != 0 的情况
                            jb.put("requestCode",1);
                            jb.put("requestResult","read ID error,please try again");
                            Thread.sleep(100);
                        }

                    }
                }
                LogUtil.e(TAG,jb.toString());
                return jb.toString();
            }
        };
        FutureTask<String> futureTask = new FutureTask<String>(callable);
        new Thread(futureTask).start();
        try {
            retStr  =  futureTask.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return retStr;
    }

    @Override
    public String printMsg(String msg) {
        printer.esc.wakeUp();
        printer.esc.text.init();
        printer.esc.text.setXY(20, 40);

        boolean succ = printer.esc.text.printOut(Printer_define.ALIGN.LEFT, ESC.FONT_HEIGHT.x24, true, ESC.TEXT_ENLARGE.NORMAL, msg);
//        printer.esc.text.printOut(Printer_define.ALIGN.CENTER, ESC.FONT_HEIGHT.x32, true, ESC.TEXT_ENLARGE.NORMAL, "每日优鲜  " + "0039-微信-水产(1/1)");
//        printer.esc.text.printOut(Printer_define.ALIGN.LEFT, ESC.FONT_HEIGHT.x24, true, ESC.TEXT_ENLARGE.NORMAL, "编码: " + "absdferr");
//        printer.esc.text.printOut(Printer_define.ALIGN.LEFT, ESC.FONT_HEIGHT.x24, true, ESC.TEXT_ENLARGE.NORMAL, "名称: " + "草鱼");
//        printer.esc.text.printOut(Printer_define.ALIGN.LEFT, ESC.FONT_HEIGHT.x24, true, ESC.TEXT_ENLARGE.NORMAL, "服务: " + "宰杀");
//        printer.esc.text.printOut(Printer_define.ALIGN.LEFT, ESC.FONT_HEIGHT.x24, true, ESC.TEXT_ENLARGE.NORMAL, "规格: " + "大杯/加糖/不加奶");
//        printer.esc.text.printOut(Printer_define.ALIGN.LEFT, ESC.FONT_HEIGHT.x24, true, ESC.TEXT_ENLARGE.NORMAL, "订单: " + "DD19032621214456879");
//        //二维码
//        printer.esc.barcode.barcode2D_QRCode(80, 230, ESC.BAR_UNIT.x4, 0, 0, "http://www.jqsh.com/front/bin/ptdetail.phtml?Part=pro_08&Rcg=1");
        printer.esc.feedLines(1);
        JSONObject jb = new JSONObject();
        try {
            if (succ){
                jb.put(ConstDefine.requestCode,ConstDefine.SUCCESS);
                jb.put(ConstDefine.requestResult,"success");
                jb.put(ConstDefine.printinfo,msg);
            }else {
                jb.put(ConstDefine.requestCode,ConstDefine.ERROR);
                jb.put(ConstDefine.requestResult,"print error");

            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return jb.toString();

    }

    @Override
    public String readPwd() {
        String pwd = null;
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return startPass();
            }
        };
        FutureTask<String> futureTask = new FutureTask<>(callable);
        new Thread(futureTask).start();

        try {
            pwd = futureTask.get();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        LogUtil.e(TAG,"pwd 11111 == " + pwd);
        return pwd;
    }
    public String passWord = null;
    KeyBroadOption option = null;
    private checkThread checkthread = null;
    public boolean breakflag = false;
    JSONObject jb = new JSONObject();
    int ret = -1;
    public String startPass(){
        option = new KeyBroadOption();
        option.setMode((byte) 0x00); //加密模式   0x03 明文模式
        option.setStartNum(1); //一次输入
        option.setMinLen((byte) 4);
        option.setMaxLen((byte) 6);
        option.setMainKeyNo(0);
        option.setTimeOut(20*1000);
        option.cardNo = "6214123456781234";
        int startNum = 0;

        byte[] pinBlock = new byte[256];
        byte [] MWpinBlock = null;
        try{
            if (getPin(pinBlock) == 0) {
                byte mode = option.getMode();
                LogUtil.e(TAG,"mode == " + mode);
                if(option.getMode() == 0x00 || mode == 0x10){
                    if(option.getMainKeyNo() >= 10){	//如果是X9.8标准 使用国钥SM4加密
                        MWpinBlock = new byte[16];
                        System.arraycopy(pinBlock, 0, MWpinBlock, 0, MWpinBlock.length);

                    }else{			//如果是X9.8标准 不使用国钥SM4加密
                        MWpinBlock = new byte[8];
                        System.arraycopy(pinBlock, 0, MWpinBlock, 0, MWpinBlock.length);
                    }

                }else if(option.getMode() == 0x03 || mode == 0x13){ //明文

                    MWpinBlock = new byte[8];
                    System.arraycopy(pinBlock, 0, MWpinBlock, 0, MWpinBlock.length);
                    LogUtil.e(TAG, "明文=="+ByteTool.byte2hex(MWpinBlock));
                }else if(option.getMode() == 0x06 || mode == 0x16){
                    MWpinBlock = new byte[102];
                    System.arraycopy(pinBlock, 0, MWpinBlock, 0, MWpinBlock.length);
                }
                startNum ++ ;
                if ( MWpinBlock != null) {
                    if(option.getStartNum() > startNum){
                        if(passWord == null){
                            passWord = ByteTool.byte2hex(MWpinBlock);
                        }else{
                            if(!passWord.equals(ByteTool.byte2hex(MWpinBlock))){
//                            callback.onFail(-8, "密码输入不一致");
                                jb.put(ConstDefine.requestCode,1);
                                jb.put(ConstDefine.requestResult,"please try again!");
                                return jb.toString();
                            }
                        }
//                    callback.onFail(ret, "请再次输入密码");
                        startPass();
                    }else{
                        if(passWord != null && !passWord.equals(ByteTool.byte2hex(MWpinBlock))){
                            jb.put(ConstDefine.requestCode,1);
                            jb.put(ConstDefine.requestResult,"please try again!");
                            return jb.toString();
//                        callback.onFail(-8, "密码输入不一致");
                        }else{
                            jb.put(ConstDefine.requestCode,0);
                            jb.put(ConstDefine.requestResult,"success");
                            jb.put(ConstDefine.password,ByteTool.byte2hex(MWpinBlock));
                            return jb.toString();
//                        callback.onReadPin(MWpinBlock);
                        }
                    }
                }
            } else if (ret == -7007) {

                    if(passWord != null && startNum != 0){
//                        callback.onFail(ret, "请重新输入");
                        startNum = 0;
                        passWord = null;
                        startPass();

                    }else{
//                        callback.onCancel();
                        jb.put(ConstDefine.requestCode,1);
                        jb.put(ConstDefine.requestResult,"canceled,please try again!");
                        jb.put(ConstDefine.password,"");
                        return jb.toString();
                    }

            } else if (ret == -7009) {
                jb.put(ConstDefine.requestCode,2);
                jb.put(ConstDefine.requestResult,"timeout,please try again!");
                jb.put(ConstDefine.password,"");
                return jb.toString();
            } else {
                jb.put(ConstDefine.requestCode,1);
                jb.put(ConstDefine.requestResult,"getPin failed!");
                jb.put(ConstDefine.password,"");
                return jb.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jb.toString();
    }

    private int getPin(byte[] pinBlock) {
        KeyBroadOption unit = option;
        byte mode = unit.getMode();
        byte keyno = (byte) unit.getMainKeyNo();
        byte maxLen = unit.getMaxLen();
        byte minLen = unit.getMinLen();
        int TimeOut = unit.getTimeOut();
        Timer timer2 = new Timer(TimeOut - 1000);
        timer2.start();
        if (mode == 0x00 || mode == 0x10) {
            byte[] cardNo_b = unit.cardNo.getBytes();
            byte[] iAmount_b = new byte[30];
            if (unit.iAmount.length() > 0) {
                byte[] c = unit.iAmount.getBytes();
                StringBuffer sb = new StringBuffer();
                for (int i = 0; i < c.length; i++) {// 输出结果
                    sb.append(Integer.toHexString(c[i] & 0XFF));

                }
                while (sb.length()<28){
                    sb.append("0");
                }
                Log.e(TAG, "iAmount:" + sb.toString().length());
                iAmount_b = StringUtil.hexStringToBytes(sb.toString());
            }
            Log.e("GJ", ""+keyno);
            try {
                ret = api.Pci_GetPin(keyno, minLen, maxLen, mode,
                        (byte) TimeOut, cardNo_b, (byte) 0, iAmount_b);

            } catch (ArrayIndexOutOfBoundsException e) {
                e.printStackTrace();

            }
        }
        boolean m_bThreadFinished = false;
        if (mode == 0x03 || mode == 0x13) {
            try {
                ret = api.Pci_GetPin(keyno, minLen, maxLen, mode,
                        (byte) TimeOut, new byte[13], (byte) 1,
                        new byte[30]);
            } catch (ArrayIndexOutOfBoundsException e) {
                e.printStackTrace();
                m_bThreadFinished = true;

            }
        }
        if(mode == 0x06|| mode == 0x16) {

            try {
                ret = api.Pci_GetPin(keyno, minLen, maxLen, mode,
                        (byte) TimeOut, new byte[13], (byte) 1,
                        new byte[30]);
            } catch (ArrayIndexOutOfBoundsException e) {
                e.printStackTrace();
                m_bThreadFinished = true;

            }

        }

        startCountDown(TimeOut);

        if (ret == 0) {// 启动成功
            if (this.checkthread != null) {
                this.checkthread.setRunFlag(false);
                this.checkthread.interrupt();
                this.checkthread = null;
            }
            this.checkthread = new checkThread();
            this.checkthread.setMode(mode);
            this.checkthread.setMaxLen(maxLen);
            this.checkthread.start();
            int ch = 0;
            do {
                do {
                    ch = api.GetPinStarNum();
                } while (ch == -1 && !breakflag && !timer2.timeOut());
                pin_input_num = ch;
                pin_input_flag = 1;
                if(ch == maxLen && (mode&0xF0) == 1){
                    LogUtil.e(TAG,"num=" + ch + " -- maxLen = " + maxLen);
                    break;
                }
            } while ((ch != 59) && ((mode < 16) || (ch < maxLen)) && !breakflag && !timer2.timeOut());
            if(timer2.timeOut()){
                ret = -7009;
                return ret; //超时
            }
            if(!breakflag) {
                ret = api.readPIN(pinBlock);
                Log.e(TAG, "api.readPIN ret =" + ret + "== pinblock=" + ByteTool.byte2hex(pinBlock));
            }else{
                ret = -7008;
            }
            Log.e("readPin_ret:", "====" + ret + "====");
            if (timer != null) {
                timer.cancel();
            }
        }
        return ret;

    }
    private void startCountDown(int timeOut) {
        TimerTask task = new TimerTask() {
            @Override
            public void run() {

                timer.cancel();
//                closeModule(true);
                api.GetPin_quit();
            }
        };
        timer = new java.util.Timer();
        timer.schedule(task, (timeOut + 10) * 1000);
    }
    private int pin_input_flag = 0;
    private int pin_input_num = 0;
    private java.util.Timer timer = null;
    public class checkThread extends Thread {
        int keyNum;
        byte m_Mode = 0;
        byte m_MaxLen;
        private boolean runFlag = true;

        public void setRunFlag(boolean runflag) {
            this.runFlag = runflag;
        }

        private boolean m_bThreadFinished = false;

        public void setMode(byte Mode) {
            this.m_Mode = Mode;
        }

        public void setMaxLen(byte MaxLen) {
            this.m_MaxLen = MaxLen;
        }

        public boolean isThreadFinished() {
            return this.m_bThreadFinished;
        }

        @Override
        public void run() {
            Log.e(TAG, "checkThread run() begin");
            synchronized (this) {
                do {
                    try {
                        this.keyNum = GetPinStarKey();
                    } catch (Exception e) {
                        break;
                    }
                    if (this.keyNum == 59) {

                        break;
                    }
//                    if (callback != null) {
//                        callback.onKeyNum(keyNum);
//                    }

                } while (runFlag
                        && ((this.m_Mode < 16) || (this.keyNum != this.m_MaxLen)));
                m_bThreadFinished = true;
            }
        }

    }
    public int GetPinStarKey() {
        Log.i(TAG, "getPinKey, wait for input key...");
        while (pin_input_flag == 0) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        pin_input_flag = 0;
        Log.i(TAG, "getPinKey pin_input_num = " + pin_input_num);
        return pin_input_num;
    }


    //读取指纹特征码
    @Override
    public String readBlueFingerMsg() {
        String retStr = "";
        final JSONObject jb = new JSONObject();
        final Timer timer = new Timer(20*1000);
        timer.start();
        final int fingerType = 1;

        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                while (true) {
                    if (timer.timeOut()){
                        jb.put(ConstDefine.requestCode,2);
                        jb.put(ConstDefine.requestResult,"timeout");
                        api.TCD_Close();
                        break;
                    }

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    APDU_RESP ApduResp_TCD = new APDU_RESP();
                    int ret = api.TCD_Read_Test(ApduResp_TCD);
                    //Log.e("RecvSendLog","结果返回"+ret);
                    if (0 == ret) {
                        jb.put(ConstDefine.requestCode,0);
                        jb.put(ConstDefine.requestResult,"success");
                        String strInfo = "";
                        byte[] fingerByte = new byte[ApduResp_TCD.LenOut];
                        try {
                            System.arraycopy(ApduResp_TCD.DataOut, 0,
                                    fingerByte, 0, ApduResp_TCD.LenOut);
                            Log.e("fingerCode:", ByteTool.byte2hex(fingerByte));
                            if (fingerType == Config.WELL_FINGER) {
                                strInfo = FingerUnit
                                        .parseWellcom(fingerByte);

                            } else if (fingerType == Config.SHENGYE_FINGER) {
                                strInfo = Base64.encodeToString(fingerByte,
                                        Base64.NO_WRAP);
                            } else {
                                strInfo = Base64.encodeToString(fingerByte,
                                        Base64.NO_WRAP);
                            }
                            jb.put(ConstDefine.result,strInfo);
                            jb.put(ConstDefine.fingerFn,"ZG");
                        } catch (ArrayIndexOutOfBoundsException e) {
                            continue;
                        }
                        break;
                    } else {
                        jb.put(ConstDefine.requestCode,1);
                        jb.put(ConstDefine.requestResult,"read error,please try again");
                        continue;
                    }

                }
                api.TCD_Close();
                return jb.toString();
            }
        };
        FutureTask<String> futureTask = new FutureTask<>(callable);
        new Thread(futureTask).start();
        try {
            retStr = futureTask.get();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return retStr;
    }



    //身份证读卡器链接状态
    public static boolean IsConId = false;
    //IC卡读卡器链接状态
    public static boolean IsConIC = false;
    //磁条卡读卡器链接状态
    public static boolean IsConMag= false;
    //打印机链接状态
    public static boolean IsConPrinter= false;
    //密码键盘链接状态
    public static boolean IsConPwd= false;
    //蓝牙指纹仪连接状态
    public static boolean BlueFinIsConFin= false;
    //USB指纹仪连接状态
    public static boolean UsbFinIsConFin= false;

}
